package command;
import functii.elementare.Constanta;
import functii.elementare.Necunoscuta;
import functii.elementare.Putere;
import functii.trigonometrice.Cos;
import functii.trigonometrice.Sin;
import operatori.Impartit;
import operatori.Minus;
import operatori.Ori;
import operatori.Plus;
import arbori.ArboreFunctional;
import arbori.Nod;


public class parsare {
ArboreFunctional radacina;
	
	/**
	 * p[]= prioritatiile operatorilor si ale operanzilor
	 */
	protected int p[]=new int[40];
	
	/**
	 * lungimeFaraP = lungimea expresiei fara paranteze
	 */
	protected int lungimeFaraP;
	
	/**
	 * numarOperatori = numarul de operatori, operanzi si paranteze
	 */
	protected int numarOperatori;
	
	/**
	 * Expresie[]: retine in oridinea in care apar fiecare element al expresiei.
	 */
	
	protected String Expresie[]=new String[100];
	/**
	 * expresie= functia de evaluat
	 */
	protected String expresie;
	
	/**
	 * sw[]= codarea intr-un singur caracter a fiecarui element al expresiei (pentru switch): sin-> s, cos->c,
	 * necunoscute si constante->x
	 */
	protected char sw[];
	
	/**
	 * pozitionSw[]= retine vechiile pozitii ale operatorilor din Expresie.
	 */	
	protected int positionSw[]=new int[100];
	
 
/**
 * Constructorul clasei BinaryTreeTest - initializeaza expresia cu cea introdusa de la tastatura
 * aloca lui sw expresie.length() pozitii.
 */
public parsare(String e)
	  {
		  setExpresie(e);
		  sw=new char[expresie.length()];
	  }
public void setExpresie(String e)
{
	  expresie=e;
}
public String CreateSw()
{
	  int i=0, numarElem=0; 
	  int len = expresie.length();
	  
	  for(i=0; i<len;i++)
		  Expresie[i]="";
	  i=0;
	  while(i<len)
	  {
		  int flag=1;
		  for(int j=i; j<len && flag!=0; j++ )
		  {
			  if(expresie.charAt(j)=='+'||expresie.charAt(j)=='-'||expresie.charAt(j)=='*'
				    ||expresie.charAt(j)=='/'||expresie.charAt(j)=='s'||expresie.charAt(j)=='c'
			  		||expresie.charAt(j)=='(' ||expresie.charAt(j)=='^' )
			  {
				  flag=0;
				 
				  if(expresie.charAt(j)=='s'&&expresie.charAt(j+1)=='i'&&expresie.charAt(j+2)=='n')
				  {
					  Expresie[numarElem]="sin";
					  sw[numarElem]=expresie.charAt(j);
				      i=i+3;
				  }
				  else
					  if(expresie.charAt(j)=='c'&&expresie.charAt(j+1)=='o'&&expresie.charAt(j+2)=='s')
						  {
						  Expresie[numarElem]="cos";
						  sw[numarElem]=expresie.charAt(j);
						  i=i+3;
						  }
						  
				  	  else
						  {
				  		  Expresie[numarElem]=Expresie[numarElem]+expresie.charAt(j);
				  		  sw[numarElem]=expresie.charAt(j);
				  		  i++;
						  }
				  numarElem++;
				  
				 
			  }
			  else
				  if(expresie.charAt(j)==')')
				  {
					  Expresie[numarElem]=Expresie[numarElem]+expresie.charAt(j);  
					  sw[numarElem]=expresie.charAt(j);
					  numarElem++;
					  flag=0;
					  i++;
				  }
				  else 
				  { 
					  Expresie[numarElem]=Expresie[numarElem]+expresie.charAt(j);
					  if(j+1<len && (expresie.charAt(j+1)=='+'||expresie.charAt(j+1)=='-'||expresie.charAt(j+1)=='*'
						||expresie.charAt(j+1)=='/'||expresie.charAt(j+1)=='s'||expresie.charAt(j+1)=='c'
					  	||expresie.charAt(j+1)=='(' ||expresie.charAt(j+1)=='^'||expresie.charAt(j+1)==')' ||expresie.charAt(j+1)=='='))
					  {
						  flag=0;
						  sw[numarElem]='x';
						  numarElem++;
				      }
					  i++;		 
						
				  }
			  
		  }
		
	  }
	  
	 String s="";
	  for(i=0;i<numarElem;i++)
	  {
		  s=s+sw[i];
	  	  positionSw[i]=i;
	  }
	 numarOperatori=numarElem;
	 return s;
}
public void prioritati(String s )
{
	  int i, j, crt, len;
	  len=s.length();
	 
	  for(i=j=crt=0; i<len;i++)
	  {
		  
		  switch(sw[i])
		  {
		  case ')': j-=10; break;
		  case '(': j+=10; break;
		  case '+': p[crt]=j+1; crt++;break;
		  case '-': p[crt]=j+1; crt++;break;
		  case '*': p[crt]=j+10; crt++; break;
		  case '^': p[crt]=j+11; crt++; break;
		  case '/': p[crt]=j+10; crt++; break;
		  case 's': if(crt!=0) p[crt]=p[crt-1]+j+12; else p[crt]=j+12; crt++; break;
		  case 'c': if(crt!=0) p[crt]=p[crt-1]+j+12; else p[crt]=j+12; crt++; break;
		  default: p[crt++]=32000;
		  }
		 
	  }
	  int aux;
	  do{
		  aux=0;
	  
	  i=0;	 
	  while(i<len)
	  {
		  if((sw[i]==')')||(sw[i]=='('))
		  {
			  aux=1;
			  for(j=i; j<len-1;j++)
				  {
				  	sw[j]=sw[j+1];
				  	positionSw[j]=positionSw[j+1];				  	
				  }			  
			  sw[len-1]='\0';
			  len--;
		  }
		  else
		  i++;
	  }
	  }while(aux==1);
	  lungimeFaraP=len;
	 	 
}

public Nod createTree( int position, int length)
{
	  
	  int min, poz;
	  min=p[position];
	  poz=position;
	  Nod a=null; 
	  
	  for(int i=poz+1;i<=length; i++)
	  {
		  if(min>=p[i])
		  {
			  min=p[i];
			  poz=i;
		  }
	  }
	 
	  if(Expresie[positionSw[poz]].equals("+"))
		  a= new Plus();
	  else if(Expresie[positionSw[poz]].equals("-"))
		  a= new Minus();
	  else if(Expresie[positionSw[poz]].equals("*"))
		  a= new Ori();
	  else if(Expresie[positionSw[poz]].equals("^"))
		  a= new Putere();
	  else if(Expresie[positionSw[poz]].equals("/"))
		  a= new Impartit();
	  else if(Expresie[positionSw[poz]].equals("sin"))
		  a= new Sin();
	  else if(Expresie[positionSw[poz]].equals("cos"))
		  a= new Cos();
	  else if(Expresie[positionSw[poz]].equals("x"))
		  a= new Necunoscuta();
	  else if(isNumber(Expresie[positionSw[poz]].substring(0,1)))
		  a= new Constanta(Double.parseDouble(Expresie[positionSw[poz]]));
	  
	  if(position<=length)
	 {  
	//  Node a= new Node(Expresie[positionSw[poz]]);
	  
	 if(position==length)
	  {	
		  a.setFStang(null);
		  a.setFDrept(null);
	  }
	  else if(sw[poz]=='s'||sw[poz]=='c')
	  		{
		  		a.setFStang(createTree(poz+1,length));
		  		a.setFDrept(null);
	  		}
	
	  else
	  {
		  a.setFStang(createTree(position,poz-1));
		  a.setFDrept(createTree(poz+1,length));
	  }
	 }
	 return a;
}

public Boolean isNumber(String c)
{
	  for(int i=1;i<=9;i++)
		  if(Integer.parseInt(c)==i)
			  return true;
	  return false;
}

public void run() 
{	  
	String s= CreateSw();
	prioritati(s);
  radacina=new ArboreFunctional(createTree(0, lungimeFaraP-1));
  radacina.getRadacina().setX(1);
  System.out.println("Traversing tree in preorder");
  printPreorder(radacina.getRadacina());   
	
}

public ArboreFunctional getArbore()
{
	  return radacina;
}

public void printPreorder(Nod node) 
{
	    if (node != null) 
	    {
	    	System.out.println("  Traversed " + node.getClass().getName());
	    	printPreorder(node.getFStang());	      
	    	printPreorder(node.getFDrept());
	    }
	  }

	
	


}
